home *** CD-ROM | disk | FTP | other *** search
- /* control.c : Compile control structures like while, for next, etc.
- * Return: class
- */
-
- /* Copyright 1990, 1991, 1992 Craig Durland
- * Distributed under the terms of the GNU General Public License.
- * Distributed "as is", without warranties of any kind, but comments,
- * suggestions and bug reports are welcome.
- */
-
- #include <os.h>
- #include "mc.h"
- #include "mm.h"
- #include "opcode.h"
-
- extern char token[];
-
- extern int
- breaklabel, contlabel, /* in mc.c */
- btv;
- extern unsigned int class; /* in mc.c */
-
- /* (while (test)(body))
- * Compiles down to:
- * 1: if (test) is FALSE goto 2 ; ignore if (test) ==TRUE
- * (body)
- * goto 1
- * 2:
- */
- comp_while()
- {
- int l1, ldone, savebl = breaklabel, savecl = contlabel,z;
-
- l1 = contlabel = genlabel(); ldone = breaklabel = genlabel();
- stufflabel(l1);
- lookahead(); /* check for TRUE or FALSE */
- if (class == BOOLEAN)
- {
- if (btv == FALSE) /* (while FALSE (body) */
- {
- groan("while loop never executed.");
- gojmp(JMP,ldone);
- }
- get_token();
- }
- else /* compile (test) */
- { compile(); type_check(BOOLEAN,0); gojmp(JMPFALSE,ldone); }
- compile(); z = class; /* compile (body), save result */
- gojmp(JMP,l1); /* jump back to (test) */
- stufflabel(ldone); /* next address after (body) */
- breaklabel = savebl; contlabel = savecl;
- /* If we did a (push-arg) and we are compiling args for a fcn
- * call, don't push RV.
- * Else we don't know what RV is because of possible
- * (break)
- */
- return (z == PUSHEDARGS) ? PUSHEDARGS : UNKNOWN;
- }
-
- /* (for (init)(test)(inc)(body)) : a glorified while
- * Compiles down to:
- * (init)
- * 1: if (test) is FALSE goto 3
- * (goto 2)
- * (inc)
- * 2: (body)
- * (goto 1)
- * 3:
- */
- comp_for()
- {
- int l1, l2, savebl = breaklabel, savecl = contlabel, z;
-
- l1 = genlabel(); contlabel = genlabel(); l2 = genlabel();
- breaklabel = genlabel();
- compile(); /* (init) */
- stufflabel(l1); /* (test) */
- compile(); type_check(BOOLEAN,0); gojmp(JMPFALSE,breaklabel);
- gojmp(JMP,l2); /* jmp around (inc) */
- stufflabel(contlabel); compile(); gojmp(JMP,l1); /* (inc) */
- stufflabel(l2); compile(); z = class; gojmp(JMP,contlabel); /* (body) */
- stufflabel(breaklabel);
- breaklabel = savebl; contlabel = savecl;
- return (z == PUSHEDARGS) ? PUSHEDARGS : UNKNOWN; /* same as (while) */
- }
-
- /* (if (test) (t) (f))
- * Compiles down to:
- * if (test) is FALSE goto 1
- * (t)
- * goto 2 ; not used if no else clause
- * 1: (f) ; not used if no else clause
- * 2: ; not used if no else clause
- * Note:
- * (if () ...) means use RV for the test.
- */
- comp_if(lastclass) unsigned int lastclass;
- {
- int l1, l2, z;
-
- l1 = genlabel();
- compile(); if (class == EMPTY) class = lastclass;
- type_check(BOOLEAN,0); gojmp(JMPFALSE,l1);
- compile(); z = class;
- lookahead(); /* check for else block */
- if (class == DELIMITER && *token == ')') stufflabel(l1);
- else
- {
- l2 = genlabel();
- gojmp(JMP,l2); stufflabel(l1);
- compile(); if (z != class) z = UNKNOWN;
- stufflabel(l2);
- }
- return z;
- }
-
- /* (cond (test1) (body1) (test2) (body2) ...)
- * A glorified if then else if then else if then else ...
- * Compiles down to:
- * if (test1) is FALSE goto 2
- * (body1)
- * goto done
- * 2: if (test2) is FALSE goto 3
- * (body2)
- * goto done
- * 3:
- * done:
- */
- comp_cond()
- {
- int l1, ldone;
-
- ldone = genlabel();
- do
- {
- l1 = genlabel();
- compile(); type_check(BOOLEAN,0); gojmp(JMPFALSE,l1);
- compile(); gojmp(JMP,ldone);
- stufflabel(l1);
- }
- while (gaze_ahead(BOOLEAN,0));
- stufflabel(ldone);
- return UNKNOWN;
- }
-
- /* (switch val val1 (body1) val2 (body2) ... [default (dbody)])
- * A simplified if then else if then else if then else
- * Compiles down to:
- * push val
- * if val1 != val goto 2
- * body1
- * goto done
- * 2: if val2 != val goto 3
- * body2
- * goto done
- * 3: ...
- * (dbody) ; the default case
- * done: pop val
- */
- comp_switch()
- {
- int l1, ldone, z;
-
- ldone = genlabel();
- compile(); z = class;
- checkit("switch",STRING,NUMBER,BOOLEAN,0);
- pushpush();
- do
- {
- lookahead();
- if (class == TOKEN && strcmp(token,"default") == 0)
- { get_token(); compile(); break; }
- else
- {
- l1 = genlabel();
- genop(DUP); compile();
- if (z != UNKNOWN) type_check(z,0); /* yukk!!! */
- genop(CMP); gojmp(JMPFALSE,l1);
- compile(); gojmp(JMP,ldone);
- stufflabel(l1);
- }
- } while (gaze_ahead(TOKEN,STRING,NUMBER,BOOLEAN,0));
- stufflabel(ldone); genop(POP);
- return UNKNOWN;
- }
-